package com.xjgc.exo;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xjgc.msibase.constant.Constant;
import com.xjgc.msibase.entity.MsiExoServer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.config.RestTemplateConfig;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * @author: 小逗号
 * @date: 2024-1-2
 * @description:
 * @since:
 */
@Slf4j
public class RestServerStandardManager {

    public Result<?> callRest(MsiExoServer exoWsServer, JSON dataJson) {
        //设置参数
        String restJsonKey = exoWsServer.getRestJsonKey();
        if (StringUtils.isNotBlank(restJsonKey)) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put(restJsonKey, dataJson);
            dataJson = jsonObject;
        }

        //设置 HttpHeaders
        String restContentType = exoWsServer.getRestContentType();
        restContentType = StringUtils.isBlank(restContentType) ? Constant.REST_CONTENT_TYPE_JSON : restContentType;
        HttpHeaders httpHeaders = new HttpHeaders();
//        httpHeaders.set(HttpHeaders.ACCEPT, "application/json");
//        httpHeaders.set(HttpHeaders.CONTENT_ENCODING, "UTF-8");
        httpHeaders.set(HttpHeaders.CONTENT_TYPE, restContentType);

        //添加token
        boolean restSecret = exoWsServer.isRestSecret();
        if (restSecret) {
            String tokenClass = exoWsServer.getTokenClass();
            String token = getToken(tokenClass);
            String tokenKey = exoWsServer.getTokenKey();
            String tokenMode = exoWsServer.getTokenMode();
            if (Constant.REST_TOKEN_MODE_HEADERS.equals(tokenMode)) {
                httpHeaders.add(tokenKey, token);
            } else if (Constant.REST_TOKEN_MODE_BODY.equals(tokenMode)) {
                if (dataJson instanceof JSONObject) {
                    JSONObject jsonObject = (JSONObject) dataJson;
                    jsonObject.put(tokenKey, token);
                } else {
                    return Result.error("外围服务接口配置错误,data type is JSONArray 无法添加token属性!");
                }
            }
        }

        //
        String restMethod = exoWsServer.getRestMethod();
        if (Constant.REST_METHOD_POST.equals(restMethod)) {
            Long readTimeOut = exoWsServer.getReadTimeOut();
            RestTemplate restTemplate = getRestTemplate(readTimeOut);
            String restUrl = exoWsServer.getRestUrl();
            Map response = restTemplate.postForObject(restUrl, new HttpEntity<>(dataJson, httpHeaders), Map.class);
            return Result.OK(response);
        } else {
            return Result.error("外围服务接口配置错误,暂不支持POST以外的请求!");
        }


    }

    /**
     * 获取认证Token
     *
     * @param tokenClass
     * @return
     */
    private String getToken(String tokenClass) {
        if (!TOKEN_SERVER_MAP.containsKey(tokenClass)) {
            try {
                Class<?> aClass = Class.forName(tokenClass);
                Object bean = SpringContextUtils.getBean(aClass);
                TOKEN_SERVER_MAP.put(tokenClass, bean);
                Method method = aClass.getMethod("getToken");
                TOKEN_METHOD_MAP.put(tokenClass, method);
            } catch (ClassNotFoundException | NoSuchMethodException e) {
                log.error("类加载失败:" + tokenClass, e);
                throw new JeecgBootException("中间库任务执行失败!");
            }
        }
        Object o = TOKEN_SERVER_MAP.get(tokenClass);
        Method method = TOKEN_METHOD_MAP.get(tokenClass);
        try {
            Object invoke = method.invoke(o);
            return invoke.toString();
        } catch (IllegalAccessException | InvocationTargetException e) {
            log.error("类加载失败:" + tokenClass, e);
            throw new JeecgBootException("中间库任务执行失败!");
        }
    }

    /**
     * token 认证javaBean
     */
    private final static Map<String, Object> TOKEN_SERVER_MAP = new HashMap<>(16);
    /**
     * token 认证javaBean 获取token方法名
     */
    private final static Map<String, Method> TOKEN_METHOD_MAP = new HashMap<>(16);


    private final static Map<Integer, RestTemplate> REST_TEMPLATE_REGISTRY = new HashMap<>(4);

    private RestTemplate getRestTemplate(Long readOut) {

        Integer readTimeOut = readOut == null ? RestTemplateConfig.DEFAULT_READ_TIME_OUT : Integer.parseInt(readOut.toString());
        if (REST_TEMPLATE_REGISTRY.containsKey(readTimeOut)) {
            return REST_TEMPLATE_REGISTRY.get(readTimeOut);
        }
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        //ms毫秒
        factory.setReadTimeout(readTimeOut);
        //ms毫秒
        factory.setConnectTimeout(3000);
        RestTemplate restTemplate = new RestTemplate(factory);
        //修改默认String转换器  默认为 charesets =  StandardCharsets.ISO_8859_1;
        restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        REST_TEMPLATE_REGISTRY.put(readTimeOut, restTemplate);
        return restTemplate;


    }

}
